home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / The World of Computer Software.iso / oobpls10.zip / OOBPLUS.DOC < prev    next >
Text File  |  1992-11-06  |  80KB  |  1,609 lines

  1.  
  2.  
  3.                    OOBPLUS - CompuServe B protocol objects
  4.                        Copyright (c) Steve Sneed 1991
  5.                              All rights reserved
  6.  
  7.  
  8.      This document and the included source code ("the material") are the
  9.   copyrighted work of their author.  The material is provided to TurboPower
  10.   Software, and a license is hereby granted to TurboPower Software, for
  11.   distribution with their product(s).  Purchasers of TurboPower Software
  12.   product(s) that include the material may use the material under the same
  13.   purchase agreement rights and restrictions as the TurboPower product(s).
  14.  
  15.      Portions of the material are copyright (c) by CompuServe, Inc. and
  16.   are used by permission.  "GIF" and "Graphics Interchange Format" are
  17.   Service Marks (sm) of CompuServe, Inc., an H&R Block Company.
  18.  
  19.  
  20. ---- Other Documentation --------------------------------------------------
  21.  
  22.      The information and code provided here is based on the BPlus spec
  23.   document, and the GIF 87a and 89a spec documents.  For anything more than
  24.   a direct "plug-n-play" implementation based on these objects you will
  25.   definitely need those documents, and both are available for download from
  26.   CompuServe.  The BPlus document is available in the IBMCOM Forum's LIBrary
  27.   10 (Protocols) as PBDOC.ARC.  The GIF 89a specification, which includes
  28.   all of the 87a spec, is available in the PICS Forum's LIBrary 14 (Misc.
  29.   Utilities & Code) as GIF89A.DOC. (Other word processor formats, such as
  30.   WordPerfect and MSWord, are available for the GIF 89a spec; BROwse the
  31.   library with a KEYword of "89A" or "SPEC" to find them.)
  32.  
  33.      The book "Programmer's Guide to PC & PS/2 Video Systems" (Richard
  34.   Wilton, Microsoft Press 1988, ISBN 1-55615-103-9) is generally considered
  35.   the "bible" of PC video programming.  Highly recommended if you intend to
  36.   work with GIF decoding.  I have also found "C Programmer's Guide to Serial
  37.   Communications" (Joe Campbell, Howard W. Sams & Company 1987, ISBN
  38.   0-672-22584-0) to be extremely helpful in general comm programming and
  39.   protocols.
  40.  
  41.  
  42. ---- Overview -------------------------------------------------------------
  43.  
  44.      The CompuServe Information Service (CIS) is the largest and most popular
  45.   system of its type in the world, with over 1,000,000 members in the US and
  46.   abroad.  CIS provides several "special" capabilities, such as the ability
  47.   to display graphics in real time and the ability to encapsulate the entire
  48.   online session within a protocol for improved data integrity and management.
  49.   Many of these special capabilities are based on CompuServe's own transport
  50.   protocol, the "B" protocol.  Because of the size and number of users of CIS
  51.   today, any communications program should provide support for at least the
  52.   basic File Transfer Protocol (FTP) portions of the B protocol.  OOBPLUS
  53.   makes providing that support simple.
  54.  
  55.      The OOBPLUS unit provides a set of objects for B protocol.  Derived from
  56.   Async Professional's AbstractProtocol object, OOBPLUS provides a "plug-in"
  57.   interface for both the B series protocol's FTP services, and the special
  58.   version for use with CompuServe's GIF graphics image display services.
  59.  
  60.      There are three distinct species of B protocol in use today:
  61.  
  62.      "Classic" B:  The original B protocol.  This version defines a protocol
  63.      similar in some ways to the XMODEM protocol but with special consider-
  64.      ation for the packet-switcher network CIS uses to connect users to their
  65.      hosts.  It uses a 512-byte block at all bps rates, a one-byte arithmetic
  66.      checksum, and simple "send block/wait for ACK" flow of control.  It does
  67.      allow for flexible block length of less than 512 bytes, and uses a fixed
  68.      quoting set (see below).  Classic B provides a much more robust protocol
  69.      environment than XMODEM for CIS, but its thruput is only slightly
  70.      better than XMODEM.  Classic B was designed in the days of 300baud
  71.      modems and early protocol technology.
  72.  
  73.      "Quick" B:  Quick B (QB) is a major enhancement over Classic B.  While
  74.      maintaining backwards compatibility with Classic B it adds "send-ahead"
  75.      technology (the ability to send more than one packet before receiving an
  76.      acknowledgement), a larger 1K packet size for better thruput with higher
  77.      speed modems, and 16-bit CRC blockchecking.  QB is designed so the host
  78.      can "handshake" with the remote and determine whether Classic B or QB
  79.      will be used.  QB was such a marked improvement over Classic B that many
  80.      comm programs rushed to support it, and some unfortunately did not
  81.      implement the handshake properly; as a result CIS had to add a new
  82.      option to all of its protocols menus just for QB.
  83.  
  84.      "BPlus": BPlus (B+) is a superset of QB, or more correctly, QB is a
  85.      subset of B+.  QB was more a preliminary version of B+ than a
  86.      self-standing version, and only the rapid implementation of QB by
  87.      several major comm programs kept it in use.  B+ defines several
  88.      extensions and enhancements over QB, such as the "TI" file information
  89.      packet type.  B+ also introduced the use of flexible maximum packet
  90.      size, to allow achievement of optimum packet size based on baud rate and
  91.      other factors.  Most importantly for users, B+ defines a method to
  92.      resume an aborted download from the point of abort in the transferred
  93.      file rather than forcing the download to restart from the beginning.
  94.      CompuServe would like to see QB disappear completely and is encouraging
  95.      developers to provide complete B+ support; many major comm programs
  96.      (such a ProComm Plus 2.0 and CrossTalk XVI and Mk 4) have done so, but a
  97.      large base of comm programs are still in use that only provide QB
  98.      support (such as BitCom, which many modem vendors distribute free with
  99.      their modems).
  100.  
  101.      B+ is not a file transfer protocol in the typical sense.  It is a
  102.   "Transport Level" protocol, and as such can be used to provide protocol
  103.   error trapping and data management to an entire online session which may
  104.   include file transfer sub-sessions.  The full B+ specification defines
  105.   multiple "layers" of protocol support, the lowest being the "Transport
  106.   Layer".  The transport layer provides the basic data packetization, flow
  107.   control and error handling.  On top of the Transport Layer may be
  108.   "Application-Specific" layer(s) which performs preprocessing (such as
  109.   decompression of compressed data) or prioritizing/directing of data to
  110.   various parts of the overall program. In order to use B+ as a full
  111.   transport protocol, the CIS host and the local program must handshake
  112.   immediately after the remote logs into the service, both for protocol
  113.   support and then for application support.  This requires the remote
  114.   software to have intimate knowledge of the host and vice versa, so this
  115.   level of B+ is currently only used by software developed by CIS itself.  B
  116.   was originally developed for the Vidtex terminals back in the late 70's and
  117.   early 80's, but currently the only software in the PC arena that uses
  118.   full-session protocol encapsulation is the Host-Micro Interface protocol in
  119.   the Compuserve Information Manager products for PCs and Macs.
  120.  
  121.      HMI NOTE: This new version of OOBPLUS now specifically includes the
  122.   modifications nessessary to support the special HMI version of B+.  However,
  123.   because no documentation has been made publicly available by CompuServe on
  124.   the exact format or usage of HMI, what's here has been arrived at by
  125.   experimentation and may require modification as more information on HMI
  126.   becomes available.
  127.  
  128.      The B+ protocol was designed with more than PCs in mind.  Many types of
  129.   computers access the CIS hosts, from Apple ]['s and RadioShack Model III's
  130.   to Cray supercomputers.  Also, CIS ties to several different telephone
  131.   networks both in the US and abroad, and many of these networks are
  132.   decidedly different from the network CIS itself owns and operates
  133.   (especially the overseas PADs and networks).  Because many of these
  134.   networks use some control characters for their own internal purposes, and
  135.   many of the mini and mainframe computers have their own interpretation of
  136.   certain characters, B+ "quotes" some characters in a manner similar to
  137.   Kermit.  This gives the protocol greater flexibility, but has the negative
  138.   effect of increasing packet overhead and slowing overall data thruput.
  139.   Classic B defined a fixed quoting set of the first 32 ASCII characters, but
  140.   this proved to be excessive for most microcomputers.  B+ allows the quoting
  141.   set to be negotiated during protocol session startup, so that the smallest
  142.   nessessary set is used to maximize thruput.
  143.  
  144.      One of the most common questions I've heard about B over the years is,
  145.   "How do I add it to my PC-based BBS?"  I cannot recommend using B+ anywhere
  146.   but on CIS for typical FTP uses.  B+ is optimized for CIS' packet-switched
  147.   networks and is the best protocol to use by far in that environment, but on
  148.   direct PC-to-PC links the high per-packet overhead of B+ causes thruput
  149.   to suffer dramatically.  Also, a B+ "host-side" program can be difficult
  150.   to interface to current BBS technology for forking protocol modules,
  151.   because the filename prompting and startup process is different from the
  152.   common protocols like XMODEM.  For BBS use, you are much better off to use
  153.   ZModem.  B+ would, however, make a good base protocol for a transaction
  154.   processing system or similar project that used serial links to other
  155.   machines (I have used a modified version of it for such a system between a
  156.   main VME-based processor and AT workstations.)  Earlier beta versions of
  157.   this library provided a host-side object derived from the BPProtoFTP
  158.   object, but recent changes in CIS policy would require each person
  159.   receiving this library to obtain a (no-cost) license directly from CIS
  160.   before receiving the source or working TPU so it has been eliminated.
  161.   (I've tried to remove all references to the BPProtoHost object throughout
  162.   this document; if I've missed some please forgive me.)
  163.  
  164.  
  165. ---- Specifics ---------------------------------------------------------------
  166.  
  167.      OOBPLUS implements the B protocols in a layered fashion, just as the CIS
  168.   hosts.  An abstract parent object handles the basic flow management and
  169.   packetization chores, while child objects implement the specific FTP and
  170.   GIF receive services.  A hierarchial diagram:
  171.  
  172.   AbstractProtocol
  173.         ├── (...other derived APRO protocols...)
  174.         └── BPProtocol                      {abstract BPlus parent}
  175.                 ├── BPProtoFTP                  {File Transfer services}
  176.                 └── BPProtoGIF                  {GIF receive/decode services}
  177.  
  178.      The BPProtocol abstract parent is derived from Async Professional's
  179.   AbstractProtocol object to take advantage of some of its variables and
  180.   methods.  Like other protocols derived from AbstractProtocol, BPProtoGIF
  181.   can be instantiated "on the fly", as it is needed. However, the
  182.   BPProtoFTP object needs to be instantiated whenever the main program is
  183.   receiving and processing characters from the commport.
  184.  
  185.      Because B is a transport level protocol, the host may send non-protocol
  186.   data between protocol packets, or between the protocol support handshake
  187.   and the first actual protocol packet.  The term "protocol session" is used
  188.   to denote some period of host-remote activity that begins with the
  189.   handshake and ends with with a termination packet.  A FTP or GIF-receive
  190.   session may be a complete protocol session, or there may be other data
  191.   and/or commands issued via protocol packets.  Some of the variables used in
  192.   the BPProtocol object and its children are "session dependent" and are
  193.   initialized whenever the handshake is performed, while others are
  194.   re-initialized each time a FTP or GIF-receive subsession is started.
  195.  
  196.      B+ requires an 8-bit data path.  The CIS hosts default to E71 port
  197.   parameters when you connect to the host, so your terminal handler must be
  198.   able to switch to N81 "on the fly" for a protocol session, and back to E71
  199.   when the session is complete.  Such a flying switch, with data streaming
  200.   into the port, is tricky to do without dropping characters.  The SetLine
  201.   method in Async Professional's AbstractPort object can be used to make the
  202.   switch.
  203.  
  204.  
  205.   Considerations for protocol handshake and initialization
  206.   --------------------------------------------------------
  207.  
  208.      Most conventional protocols, such as XMODEM, are considered "receiver
  209.   driven" because whichever end of the protocol link is receiving the primary
  210.   data flow manages the protocol.  B+ on the other hand is considered "host
  211.   driven", because one end of the link is the "master" or host while the
  212.   other is the "slave" or remote, irrespective of the direction of primary
  213.   data flow.  On CIS, the host is always the CIS computer, with the local
  214.   PC system being the remote.
  215.  
  216.      Starting XMODEM is typically a two-step process: you start XMODEM on the
  217.   other end of the link, and then you start it on the local end.  B+ doesn't
  218.   work this way; the host always starts the actual protocol processing
  219.   session via command to the remote, without user intervention.
  220.  
  221.      B+ handles this as a two-step process.  First the host issues an <ENQ>
  222.   char to the remote.  When the remote "sees" an <ENQ> in the incomming
  223.   data, it calls the BPProtocol.HandleENQ method.  This method responds with
  224.   a specific sequence of characters as a "support/sync handshake":
  225.  
  226.      for Classic B:  <DLE><'0'>
  227.      for QB:         <DLE><'+'><DLE><'0'>
  228.      for B+:         <DLE><'+'><'+'><DLE><'0'>   (we use this)
  229.  
  230.   This tells the host what level of B is supported by the remote and that
  231.   the remote's initial packet sequence number will be 0.  It also initializes
  232.   several internal variables that are protocol-session dependent.  Once the
  233.   remote has responded to the <ENQ>, the host may at any time (but not
  234.   nessessarily immediately or as the next char) send the remote the
  235.   two-character sequence <DLE><'B'>, the first two characters of a protocol
  236.   packet. The remote software's terminal handler must look for any <DLE>
  237.   received and call the protocol handler function bpDLESeen; the bpDLESeen
  238.   method verifies the <'B'> char and continues protocol processing or exits
  239.   as is appropriate.
  240.  
  241.      This means that the protocol handler object needs to be instantiated
  242.   when you start your terminal handler loop (or before), so that the <ENQ>
  243.   handshake properly initializes the nessessary vars in the object for later
  244.   when the <DLE><'B'> sequence is received.  For FTP and GIF uses, the
  245.   <DLE><'B'> will almost always immediately follow the <ENQ> response, but
  246.   for non-FTP purposes this may not be the case so we have to handle it that
  247.   way.  Also, you can set your user options at the CIS host end so that an
  248.   <ENQ> is sent immediately after login (as a handshake) without starting
  249.   a protocol session, so the <ENQ> must be handled throughout the online
  250.   session.
  251.  
  252.  
  253.   Packet definition and layout
  254.   ----------------------------
  255.  
  256.      B Protocol "packets" are like XMODEM "blocks", but the term packet is
  257.   used because the actual data within may be self-standing and have no
  258.   connection to data in previous or subsequent packets.  Each packet provides
  259.   the information nessessary for the packet handler to determine what to do
  260.   with the data, and even within a FTP or GIF session there may be packets
  261.   that do not contain file data.  For example, in the CompuServe Information
  262.   Manager, when performing a FTP some packets are not file data but instead
  263.   is data used to update the "tracking" status line at the bottom of the
  264.   screen.  During a protocol session, all commands and data in both
  265.   directions, other than packet ACKs/NAKs, are sent via packets.
  266.  
  267.      The layout of a B packet:
  268.  
  269.        <DLE><'B'><SeqNum><...quoted data...><ETX><quoted checkvalue>
  270.  
  271.   The <DLE><'B'> identifies this as a B protocol block.  The <SeqNum> field
  272.   is an ASCII digit 0 thru 9 (ASCII $30 to $39) incremented each packet and
  273.   wrapping back to 0 from 9.  <...quoted data...> is the data block for this
  274.   packet, and contains any command info needed by the packet handler as well
  275.   as any "raw data" that might be needed in this packet.  The data is quoted
  276.   as nessessary to protect volatile characters.  <ETX> is the "end-of-packet"
  277.   flag character, and is sent unquoted.  <Quoted checkvalue> may be either a
  278.   one-byte arithmetic checksum or two-byte CRC depending on negotiated
  279.   settings (see below), and is quoted as nessessary.  Any given packet can be
  280.   a maximum of 1024 data bytes in size and can be less (as few as one byte).
  281.   The maximum size to expect is defined per handshake, and typically is
  282.   chosen based on current baud rate to provide a good balance between thruput
  283.   on good packets against turn-around time on flawed packets.  CIS has shown
  284.   the best average has proven to be a maximum packet size that gives a packet
  285.   transmission time of 4 to 5 seconds at the current bps rate; at 300baud the
  286.   packet size should be 128 bytes, at 1200bps it should be 512 bytes, and at
  287.   2400bps and above it should be 1K bytes.
  288.  
  289.      Quoting is performed by sending a <DLE> followed by the quoted data
  290.   byte. If the byte to be quoted in in the range $00..$1F, it is OR-ed with
  291.   $20 before sending, and if in the range $80..$9F it is OR-ed with $60.
  292.   When the receiving side sees a <DLE> in the packet other than in the
  293.   header, it assumes the next byte is quoted and reverses the sender's
  294.   quoting after discarding the <DLE>.  The checksum/CRC calc is performed on
  295.   the byte's "natural" value, i.e. the CRC or checksum calc is performed on
  296.   the byte before quoting on the sending side and after the byte is un-quoted
  297.   on the receiving side. The <DLE> is discarded without inclusion in the
  298.   checksum/CRC calculation.
  299.  
  300.      Classic B used a fixed quoting set, all chars in the range $00..$1F.
  301.   This proved to be excessive on most systems, increasing overhead
  302.   unnessessarily.  In PC-based applications on most networks, only six
  303.   characters actually need to be quoted: <DLE>, <ENQ>, <ETX>, <XON>, <XOFF>
  304.   and <NAK>.  The first three and <NAK> are used by the protocol itself and
  305.   must be protected to prevent the protocol from becomming confused, and the
  306.   flow control chars must be quoted to prevent unintended XOFF deadlocks.
  307.   Other platforms require different quoting sets, so B+ defines several
  308.   "standard" sets, but we only use 2: DQDefault (the minimum 6-char set) and
  309.   DQFull (the full set, equal to the Classic B set).  For B+, DQFull is only
  310.   used during handshake, since at that point we have not negotiated the
  311.   quoting set and protocol level, and must assume the worst.
  312.  
  313.      Each packet from either end must be acknowledged by the receiving end,
  314.   although such acknowledgements may be delayed so that multiple packets are
  315.   outstanding.  Positive acknowledgements (ACKs) are sent as <DLE><SeqNum>
  316.   where <SeqNum> is the sequence number of the packet being ACKed.  Negative
  317.   acknowledgements (NAKs) are sent as a single <NAK> character.  Since the
  318.   NAK does not specifiy to which packet it applies, the packet handler must
  319.   keep track of how many packets are outstanding and assume the NAK refers to
  320.   the oldest.  This also means that when a NAK is received, *all* outstanding
  321.   packets are discarded in order to keep the sequencing straight.  Obviously,
  322.   the higher the number of outstanding packets, the greater the amount of
  323.   data that is resent - and the longer the "turn-around" time on a protocol
  324.   error.  B+ is currently defined as having a maximum of 2 outstanding
  325.   packets.  Tests by CIS have proved that more than two do not noticably
  326.   improve thruput while seriously degrading performance on error turn-around.
  327.  
  328.  
  329.   Packet types
  330.   ------------
  331.  
  332.      Although all packets follow the above format, packets have different
  333.   types.  The first data byte of the packet (sometimes the first 2 bytes)
  334.   defines the packet's type and is not part of other data in the packet.  For
  335.   FTP and GIF uses, the only types we are concerned with are "T", "N", "F"
  336.   and "+" packets.
  337.  
  338.      "T" packets are transfer management packets.  There are several subtypes
  339.   of this packet type, used for specific transfer management jobs.  "N"
  340.   packets are "Next Data" packets, meaning they contain data that is a
  341.   continuation of the previous packet(s).  "F" packets are Failure packets
  342.   and mean the protocol session is aborting for some reason.  Again, there
  343.   are several possible "F" packet types depending on the reason for the
  344.   failure.  The "+" packet is the special BPlus Parameters Handshake packet
  345.   used during protocol initialization.
  346.  
  347.      "T" packets fall into the following categories:
  348.  
  349.         "T"   - Transfer Init.  This packet contains the file type (Binary or
  350.                 ASCII), the transfer direction relative to the remote (Upload
  351.                 or Download), and the file's name for the remote's storage.
  352.                 Sometimes called the "TD" packet.
  353.  
  354.         "TI"  - Transfer Information.  This packet can contain several
  355.                 different pieces of information (see the full B+ spec for a
  356.                 detailed description of the fields in this packet).  We
  357.                 currently only use the FileSize field.
  358.  
  359.         "TC"  - Transfer Complete.  Signals the end of the current file.
  360.                 This packet will never contain file data; the last previous
  361.                 "N" packet contained the end of the file or GIF data.
  362.  
  363.         "Tr"  - Resume Request.  Special-case packet, sent by remote to
  364.                 request the host attempt a resume.  The "Tr" packet will
  365.                 contain the size of the file (in bytes) that resides on the
  366.                 remote's disk, and a CRC of the file calculated in the same
  367.                 manner as a packet's CRC checkvalue.  Note that CIS does not
  368.                 currently support Upload Resume (where the CIS host resumes
  369.                 a failed transfer of a file sent by the remote.)
  370.  
  371.         "Tf"  - Transfer Resume Failed.  Special-case packet, sent when a
  372.                 resume attempt request made by the remote failed.  When the
  373.                 remote requests a resume attempt it sends the length and CRC
  374.                 of the "piece" of the file it has; the host verifies it's
  375.                 local file is at least as long and has an equal CRC over the
  376.                 matching length, and if either test fails the host sends this
  377.                 packet.
  378.  
  379.      The "N" packet is pretty much self-explanatory; it is a "Next Data
  380.   Block" packet and contains only actual file contents data.  Since B packets
  381.   can be any length from one byte up to the maximum specified length, only
  382.   the exact file length is transmitted without padding.
  383.  
  384.      "F" packets are typically sent for one of three reasons: the remote's
  385.   user requested the protocol be aborted via keystroke or other manual
  386.   method, the protocol has detected a hard failure such as too many
  387.   sequential error packets, or the remote experienced a file I/O error.
  388.   The host can issue Failure packets as well, and although they are rare we
  389.   must be prepared for them.
  390.  
  391.      Typical Failure packet types:
  392.  
  393.        "FA"  - Failure/Aborted.  Sent when the user requested an abort.
  394.  
  395.        "FN"  - Failure/Not known.  Sent when an unsupported service was
  396.                requested by the host.  CIS supports several file types
  397.                besides Binary and ASCII (for use on non-PC systems), but we
  398.                can't handle them so we send a FN if the file type is not
  399.                Binary or ASCII.  Also, transfer direction flags other than
  400.                Upload and Download may be used on non-PC systems, so if we
  401.                see a direction flag other than "U" or "D" we send a FN
  402.                packet.
  403.  
  404.        "FE"  - Failure/Error.  Usually sent when a hardware error occurs,
  405.                such as file I/O error.
  406.  
  407.      Only the first two characters in a Failure packet have meaning to the
  408.   CIS hosts, the "F" and the failure-type flag.  Traditionally a text string
  409.   is also sent in the packet as descriptive info on the failure, but this is
  410.   only for use by the remote if it chooses to display the reason string.
  411.   OOBPLUS follows this tradition.
  412.  
  413.      The "+" packet type is a special case.  It provides a method for the
  414.   host and remote to negotiate what level of B+ capabilities is to be
  415.   supported during this session and the quoting set to be used.  The "+"
  416.   packet is typically sent between the <ENQ> handshake and the "T" packet.
  417.   The host sends its "+" packet first with its capabilities, and the remote
  418.   compares this information to its own capabilities and sends back a "+"
  419.   packet with what it can support.  The usual "+" packet handshake will set
  420.   the number of outstanding packets that can be supported both on send and
  421.   receive, the type of checkvalue used (CRC or arithmetic checksum), the
  422.   maximum size of a packet in this session, whether the host will support
  423.   download and/or upload resume and whether the remote can support it, and
  424.   the quoting set to be used.  See the interface section of OOBPLUS and the
  425.   ProcessTransportParams method of the BPProtocol object for more detail.
  426.  
  427.  
  428.   Flow of control
  429.   ---------------
  430.  
  431.      The overall flow of control of a B protocol session is basically the
  432.   same whether the transfer direction is Upload (from remote to host) or
  433.   Download (from host to remote).  A diagram of a typical download is the
  434.   easiest way of visualizing the flow.  An upload would be the same except
  435.   for the direction of the "N" packets and the possible resume request (no
  436.   resume on uploads).  Notice that the host always starts the ball rolling.
  437.   (The following information is specific to FTP and GIF uses of the BPlus
  438.   protocol.  Exact ordering may be different in non-FTP or GIF uses such as
  439.   HMI.)
  440.  
  441.  
  442.     HOST                                           REMOTE
  443.     ----                                           ------
  444.   <ENQ> sent            ----------->              Init vars,
  445.  
  446.   Receive ENQ resp.     <-----------          Send ENQ Response
  447.   Set vars to match
  448.  
  449.      ... (possible non-protocol data flow between sides) ...
  450.  
  451.   (NOTE 1)
  452.  
  453.   Send "+" packet       ----------->     Compare host's options with ours,
  454.                                          set our options to "best-fit"
  455.                                          the host's settings
  456.  
  457.   Configure to match    <-----------     Send "+" packet with our options
  458.   remote's capabilities
  459.  
  460.      ... (possible non-protocol data flow between sides) ...
  461.  
  462.   (NOTE 2)
  463.  
  464.   Send "T" packet       ----------->     Process "T" packet info, enter
  465.                                          protocol FTP mode, open file
  466.  
  467.   {!! IF FILE DOES NOT EXIST, SKIP TO "JUMP HERE" !!}
  468.  
  469.   (NOTE 3)
  470.                                          File exists: calc CRC on file,
  471.                                          build "Tr" packet with file's
  472.                                          size and CRC,
  473.   Gets "Tr" packet,     <-----------     send "Tr" packet
  474.   check size & CRC:
  475.  
  476.   IF AND ONLY IF the
  477.   file size and/or CRC
  478.   checks fail, send
  479.   empty "Tf" packet     ----------->     "Tf" recd, rewind on file (either
  480.                                          overwrite from beginning, abort or
  481.                                          question the user what to do)
  482.  
  483.   ELSE send first
  484.   "N" data packet,
  485.   contents of which
  486.   are assumed to
  487.   be appended to
  488.   the existing file     ----------->     append data to file, ACK packet
  489.  
  490.  
  491.   {JUMP HERE}
  492.   Send "N" packets      ----------->     write data to file, ACK packet
  493.      ...(as many times as needed)...
  494.  
  495.   Send "TC" packet      ----------->     Close file, flush pending ACKs,
  496.                                          exit FTP mode
  497.  
  498.       ...(back to normal terminal operations)...
  499.  
  500.  
  501.   Notes:
  502.  
  503.   1) If the host is to send a GIF stream for decode/display, it will send the
  504.   "Start GIF Decode" sequence immediately before the "+" packet.  It will
  505.   also send an <ENQ> after the start-decode sequence, so we must handle it.
  506.  
  507.   2) If in GIF decode mode, there will be no "T" packet as it is unnessessary
  508.   (there is no filename, and the direction and data type are fixed at
  509.   Download and Binary).  The first packet after the "+" packet will be the
  510.   first "N" packet of the GIF stream's data.
  511.  
  512.   3) No resume is possible on a GIF stream; it always starts from the
  513.   beginning.
  514.  
  515.  
  516.   Performance, thruput and packet size
  517.   ------------------------------------
  518.  
  519.      When send-ahead is enabled (QB or B+ mode), multiple packets can be
  520.   outstanding (meaning no ACK or NAK has been processed for that packet).
  521.   The design of B+ is such that it always tracks the number of packets that
  522.   are outstanding rather than a specific offset within the file (ala ZModem)
  523.   or other criteria.  This simplifies the tracking process, but it has the
  524.   negative effect of requiring all outstanding packets to be discarded and
  525.   resent when a packet is NAKed for some reason.
  526.  
  527.      Ultimate thruput for any protocol is a function of several factors: the
  528.   port speed, percentage of overhead, turnaround delays on packet ACKs, and
  529.   turnaround delays caused by defective packets that must be resent.  B+
  530.   essentially eliminates ACK turnaround delays, so raw thruput will closely
  531.   approach the raw port speed.  On binary transfers, B+'s quoting overhead
  532.   will typically reduce data thruput to 92% - 96% of the raw thruput, while
  533.   ASCII transfers will seldom be less than 98% of raw thruput.  However, if
  534.   one or more packets are defective and must be resent, the turnaround delay
  535.   for the defective packet will be several seconds because multiple packets
  536.   must be discarded and resent.  Obviously this seriously degrades overall
  537.   thruput, although the degredation percentage is a function of the number of
  538.   packets in the transfer, the size of a packet and the number of "hits" that
  539.   cause turnaround. A substantial amount of testing has been performed by CIS
  540.   personnel on this subject, and it has been determined that a send-ahead
  541.   window of 2 packets gives the best thruput with minimal turnaround delay,
  542.   when used with a packet size that gives a per-packet transmission time of 4
  543.   to 5 seconds at the current port bps rate.  Smaller packets improve
  544.   turnaround delay substantially, but hurt thruput on "clean" packets;
  545.   packets larger than 1024 bytes do not markedly improve clean thruput but
  546.   seriously hurt turnaround times.  I have implemented packet size as a
  547.   function of port bps rate in the same manner and using the same criteria as
  548.   CIS software, but my own experimentation has shown that, at 2400bps, a
  549.   512-byte packet size reduces average data thruput by only 2% - 5% while
  550.   reducing turnaround delays 50%.  A like reduction of default packet size at
  551.   1200bps produces similar results.  For most users the "factory settings"
  552.   will be fine, but you may wish to make max packet size settable via
  553.   external configuration to provide greater flexability - for example,
  554.   providing a config option for "normal lines" or "noisy lines", and reduce
  555.   the max packet size setting if the "noisy lines" option is selected.
  556.   NOTE: current B+ implementations on CIS do not support re-negotiation of
  557.   transport parameters during FTP or GIF sessions once a given protocol
  558.   session has started, although it will "drop out" of send-ahead mode and
  559.   revert to "send and wait ACK" mode if it sees a high percentage of
  560.   defective blocks.  The special version of B+ used by CIS hosts for HMI
  561.   does support such re-negotiation.  Adding re-negotiation capability for
  562.   standard FTP and GIF sessions would be wonderful, but would break existing
  563.   implementations.
  564.  
  565.  
  566.   Other things
  567.   ------------
  568.  
  569.      Most developers will implement watching for <ENQ>, <DLE> and GIF Decode
  570.   Start signals from the host within some sort of terminal emulation code,
  571.   possibly based on Async Professional's OOEMU unit's ANSI emulator.  CIS
  572.   supports ANSI/VT100, so this is convenient and works well.  However, be
  573.   aware of one point: CIS hosts actually use VT100 terminal command
  574.   sequences.  VT100 and DOS ANSI (ANSI.SYS and emulators built to mimmic it)
  575.   are both unequal and improper subsets of the full ANSI X3.64 terminal
  576.   control standard.  Specifically, DOS ANSI handles defaults on the "J" and
  577.   "K" commands differently than VT100, and an emulator that exactly mimmics
  578.   DOS ANSI will find itself clearing the whole screen at the wrong times.
  579.   Be sure your emulator setup processes the "J" and "K" commands in the
  580.   VT100 manner when on CIS.
  581.  
  582.      CIS also can support a subset of the VT52 sequences.  The <ESC><'I'>
  583.   interrogation is a VT52 sequence, for example.  You may wish to implement
  584.   VT52 processing as well as VT100 to eliminate potential misunderstood
  585.   commands.  A child of Async Professional's AnsiEmulator can easily be
  586.   derived that handles both command sets within one emulator, and is
  587.   recommended.
  588.  
  589.      When you log on to CIS, the node you call defaults to Even parity/7
  590.   data bits parameters.  As mentioned above, a proper full B+ implementation
  591.   needs to know when to switch to N81 parameters for the actual protocol and
  592.   back once the protocol session is complete, but port and/or modem hardware
  593.   can cause problems with the switch.  You are usually better off to force
  594.   N81 parameters for the entire online session.  To do so you need to ignore
  595.   both parity and framing errors from the port handler, and to mask all
  596.   incomming non-protocol chars to 7 bits.  CIS has a user configuration
  597.   option to select N81 parameters, but this won't become active until you
  598.   have logged in to CIS, so be prepared to cope.  The TERMBP example program
  599.   demonstrates one method of handling this.
  600.  
  601.      CIS supports other networks besides its own.  Such "suplimental
  602.   carriers" often behave differently than CIS' own network.  Tymnet in
  603.   particular seems to have occasional problems, though these are usually
  604.   specific to the node you call.  Specifically, Tymnet uses a PAD (Packet
  605.   Assembler/Disassembler) system that uses the <DLE> char as a signal
  606.   itself.  In order for CIS to use the <DLE> char for its own purposes, it
  607.   must tell the Tymnet network to consider that char "transparent".  CIS
  608.   issues the nessessary command automatically, but some Tymnet nodes are
  609.   slow to update themselves.  In this case the <DLE> is seen as a PAD
  610.   command and is "swallowed" by the Tymnet node.  Tymnet then sees the <'B'>
  611.   as an unknown command and issues a "pad command error" string to the
  612.   remote.  Meanwhile CIS thinks it has switched things and has sent the "+"
  613.   packet, and is waiting for a response.  A long timeout ensues.  This
  614.   doesn't seem to crop up too often on normal FTP transfers, but is not
  615.   uncommon on GIF sends.  Thankfully this problem only seems to occur on a
  616.   few nodes.
  617.  
  618.  
  619. ---- GIF Information --------------------------------------------------------
  620.  
  621.      First off, if you intend to implement GIF decoders, either off- or on-
  622.   line, you absolutely need the GIF 89a spec document.  It can be obtained on
  623.   CompuServe (see the top of this file for info.)  OOBPLUS is primarily a B
  624.   protocols unit, with GIF decoding technology provided as demonstration
  625.   only; trying to go into detail on GIF itself and the internals of a GIF
  626.   decoder is really outside the bounds of this document.  However, the GIF
  627.   spec documents provide very little information on actual online decoder
  628.   implementation details other than some general rules.  I'll try to fill
  629.   those gaps here.
  630.  
  631.      GIF (Graphics Interchange Format (sm)) is a definition for transmission
  632.   and display of raster-based graphics image data - in other words,
  633.   "bit-mapped" graphics.  GIF supports images of up to 2048 by 2048 pixels
  634.   and up to 256 colors.  Extensions allow support for "full-color" images
  635.   such as 24-bit Targa.  GIF provides services for anamation and text display
  636.   as well.  GIF was developed by CompuServe as a medium for online graphics,
  637.   with an eye towards future development in online graphics environments (ala
  638.   Prodigy.)  GIF in combination with "Transport Layer" B+ protocol provides a
  639.   rich platform for this type of environment.  GIF rapidly gained acceptance
  640.   in the file-based imaging world as well, because of its space efficiency,
  641.   ease of processing and device independence - so rapidly, in fact, that
  642.   online GIF development has been practically non-existant.  CIS early on
  643.   set up a "Developer's Group" of graphics specialists and programmers to
  644.   help steer the directions of GIF, but only myself and one other member of
  645.   that group worked primarily with the online development aspects of the
  646.   spec (and that other member has pretty much ceased online development.)
  647.   Not surprizingly, only myself and one or two other members of that group
  648.   develop primarily in Turbo Pascal; C and assembler are the norm.
  649.  
  650.      My primary purpose in providing both the GIF children to the B+ objects
  651.   and the example decoders is to spark interest in GIF development,
  652.   especially online.  The horizons opened up by realtime online graphics are
  653.   huge; the surface has only been barely scratched.  I am deluged with calls
  654.   from other developers and even more from companies and individuals with
  655.   some idea for online graphics usage, wanting me to write this or that
  656.   program (even whole BBS systems with built-in GIF databases!); I've taken a
  657.   couple of these contracts but there's many, many more where they came from.
  658.   (Tip: the real estate industry especially seems to be hurting for a good
  659.   BBS-type system for Boards Of Realtors or Brokers to run for their agents,
  660.   that provides a database of listings with images made from pictures of the
  661.   properties.  I get more requests in this area than any other.  I'm not sure
  662.   why but Medical Imaging is another popular area, although GIF's standard
  663.   color resolution is generally considered insufficent for many medical
  664.   imaging needs.)
  665.  
  666.  
  667.   GIF general info
  668.   ----------------
  669.  
  670.      GIF is a stream format.  Besides making it simple to implement online
  671.   display, this means GIF image data may formally be included in other data
  672.   or that multiple GIF streams may easily be made into a "graphics database".
  673.   CIS has steadfastly refused to formally define a "file format" for GIF, but
  674.   a format for file storage has evolved over the years and is adhered to by
  675.   all known decoders whose primary purpose is display of GIF files.  As long
  676.   as the first 6 bytes of the file's contents are the GIF signature
  677.   ("GIF87a" or "GIF89a"), the image data is contiguous and a valid
  678.   terminator exists, it can be handled by most any offline decoder.
  679.  
  680.      CIS maintains a "storage class" flag for each file in its forum
  681.   libraries. If you BROwse a library's directory, you will see a "/bin" or
  682.   "/gif" or "/rle" next to the filename on many entries.  When uploading a
  683.   file to CIS, you are prompted for, among other things, the file's type.
  684.   Most users assume that "binary" and "ASCII" are all there is, but GIF image
  685.   files should be uploaded with a file type of "GIF".  Even if a file
  686.   contains a GIF image and has filename extension of ".GIF", CIS will not
  687.   allow online display of the file's contents unless the file's storage class
  688.   is GIF as well.
  689.  
  690.      GIF image data, with the exception of the header blocks, is binary
  691.   raster-based sequential pixel color data, compressed using a modified form
  692.   of the LZW compression method.  The image raster data is uncompressed on
  693.   the fly as it is being displayed.  It is somewhat difficult for the LZW
  694.   decompressor to itself determine when a invalid byte is received - usually
  695.   it is not detected until it has corrupted the codes table in the decom-
  696.   pressor, often leading to a lockup.  Most decompressors do no or only
  697.   minimal error-checking; they assume the data handed to them is valid.
  698.   For this reason the GIF spec notes that the image data stream must be
  699.   guaranteed error-free.  For disk-based streams this is assumed, but for
  700.   online decode the stream must be protected by protocol.  The GIF spec does
  701.   not define one particular protocol that is recommended for image streams.
  702.   This is important for the bigger world of Bulletin Board Systems; it means
  703.   that it is perfectly acceptable to implement an online GIF decoder that
  704.   uses ZModem or some other protocol, so that users of BBS' without CIS B+
  705.   support can still easily view GIF images in an online environment.  Since
  706.   the main thrust of this unit is the B+ protocol I am only detailing
  707.   decoding GIF streams from B+ encapsulation, but careful study of the
  708.   example code in OLGIF.PAS should make it fairly obvious how to implement a
  709.   GIF decoder using the other protocols Async Professional provides.
  710.  
  711.     The GIF spec does define the two protocols CIS computers will use for
  712.   transmission of online GIF display streams: raw stream data (assumed to be
  713.   protected by a link-level protocol such as MNP or V.42, and not to be used
  714.   without such link-level protection) and B+ protocol.  It also defines a
  715.   "handshake" system to be used to determine both that GIF is supported for
  716.   online display, and what level of protocol and hardware support is
  717.   available on the particular remote.  While only CIS uses this handshake
  718.   system, it behooves developers to support it for online decoders based on
  719.   other protocols as well, as a standard needs to evolve on this particular
  720.   point.
  721.  
  722.      The handshake consists of 3 different "private" ANSI command sequences
  723.   ("private" because only CIS defines them).  These use the standard ANSI
  724.   X3.64 introducer sequence (<ESC><'['>) followed by a right pointer bracket,
  725.   a numeric code specifier and the command type tailer character. The
  726.   sequences are:
  727.  
  728.   <ESC>[>0g   - sent by host to interrogate remote for GIF/protocol/hardware
  729.                 support.  If the remote supports GIF display, it returns a
  730.                 string consisting of codes that tell the host to use raw
  731.                 stream or B+ transmission, what screen resolutions (X by Y,
  732.                 and number and depth of colors), whether hardcopy output is
  733.                 supported, and which version of the spec the decoder supports
  734.                 (87a or 89a).  See the spec document for the various details
  735.                 of this code scheme.
  736.  
  737.   <ESC>[>1g   - begin online decoding to the local screen.  This will be sent
  738.                 by the host immediately before the <ENQ> to handshake B+
  739.                 support. Once this is received, you can safely assume that
  740.                 the next <ENQ> will be to handshake the start of a B+ session
  741.                 to transmit the GIF stream.  Non-B+ sessions will see the
  742.                 next char after the command be the first char of the GIF
  743.                 signature starting the image data.
  744.  
  745.   <ESC>[>2g   - begin decoding to the local hardcopy device.  Lots of systems
  746.                 still in use simply do not have the video capabilities to
  747.                 adequately display GIFs, especially the higher-resolution/
  748.                 high number of colors images available from many sources.
  749.                 Also, some areas of the service provide graphics that are of
  750.                 more use as hardcopy than on the screen (such as the weather
  751.                 maps, or the stock performance graphs in the TRENDS area).
  752.                 I don't support hardcopy decode in this set of examples, but
  753.                 it is fairly easy to implement and a handy capability.  The
  754.                 handhake sequence above can be used to tell the host we want
  755.                 hardcopy decode, and for color printers can tell the host
  756.                 to use provide normal color information.
  757.  
  758.   One important note concerning the "0" code above: it is *not* sent every
  759.   time an online GIF decode is requested.  In the forum areas of CIS, it is
  760.   usually sent the first time you request a online decode and not sent again
  761.   until you leave that forum, either to another area of CIS or back to the
  762.   same forum.  Most of the non-forum areas of CIS that support GIF at all
  763.   make GIF support their primary purpose, such as the weather maps areas and
  764.   TREND; these areas will send the "0" inquiry when you first enter the area
  765.   before they display any menu text or prompts.  Your program must be able to
  766.   handle the "0" inquiry at any time, just as it must be able to process a B+
  767.   <ENQ> or <DLE> at any time.
  768.  
  769.      Until recently there were a few areas of CIS that provided GIF support
  770.   but did not support B+ encapsulation (the TREND area was the most commonly
  771.   accessed.)  These areas defaulted to raw stream even if the remote reported
  772.   its ability to handle B+, so a decoder had to be able to determine if B+
  773.   was initializing or not and process incomming data accordingly.  As you can
  774.   imagine, this lead to a lot of headaches, and problems for users when the
  775.   unprotected stream took a line hit and locked up the system.  To the best
  776.   of my knowledge there are no such areas left on CIS; all areas that provide
  777.   any support for online GIF decoding support B+ encapsulation, and all areas
  778.   support B+ by default unless specifically told otherwise by the "0" code
  779.   response string described above.
  780.  
  781.      The flow of control for B+ when processing a GIF stream for display is
  782.   very little different from a "normal" FTP session, with a couple of notable
  783.   exceptions:
  784.  
  785.   1) As mentioned in the B+ infomation above, there is no "T" packet sent
  786.   during a GIF display.  Since many of CIS' GIF streams are built and sent
  787.   "on the fly" in real time they have no filename, and obviously the
  788.   transfer's direction and data type are fixed at "Download" and "Binary".
  789.   This only complicates matters a little bit, and only if you are writing the
  790.   image data to a file as well as displaying it (something every online
  791.   decoder should do, but that CompuServe's own software products do not.)
  792.   If you do write the image to a file, it's your responsibility to determine
  793.   a name for the file and manage getting the stream data into the file; see
  794.   OLGIF.PAS and TERMBP.PAS for an example.  Such processing really should be
  795.   part of the BPProtoGIF object, but I have not included it that way because
  796.   the spec does not define the capability; you may wish to derive a child of
  797.   BPProtoGIF that does.
  798.  
  799.   2) The data in each "N" packet is yours to do with as you wish.  The
  800.   BPProtoGIF object provides a method (bpGetGIFDataBlock) that gets the next
  801.   pending "N" packet and hands you the data within it; what you do with it
  802.   from there is your business.  This provides an example of possibilities for
  803.   non-FTP uses of B+, but it also points out that protocol management is to a
  804.   large extent outside the bounds of the BPProtoGIF object - if you don't
  805.   call bpGetGIFDataBlock, or fail to call it in a timely fashion, the
  806.   protocol will time out and abort.  Also, to give the GIF decoder enough
  807.   power to properly manage the protocol flow, packets must be ACK-ed by the
  808.   GIF decoder itself (defective packets are handled automatically within the
  809.   GetPacket method of the BPProtocol parent of BPProtoGIF).  The same goes
  810.   for sending "F" packets in case the user wants to abort the decode or the
  811.   decoder itself has a problem.  With power comes responsibility; study the
  812.   OLGIF.PAS file for an example of how to manage the flow control properly.
  813.  
  814.  
  815.   OOBPLUS and GIF
  816.   ---------------
  817.  
  818.      GIF data may come from a single file, the serial port, as a piece of a
  819.   file from database-type storage, etc., and may be sent to the screen, a
  820.   printer, or some other output device, so it makes sense to isolate the
  821.   process of getting the stream's raw data and outputting the processed image
  822.   data from the decoder's inner workings.  Doing so also makes implementing a
  823.   GIF decoder thru a protocol much easier.  The demo decoders' kernel
  824.   (DEGIF.PAS) names two procedure pointers, one to a function which returns
  825.   the next byte of raw data and one that does something with a processed
  826.   raster line of display data, and refers only to these proc pointers for
  827.   source and destination.  Various "shells" can then be wrapped around the
  828.   decoder to implement the routines for a particular decoder's needs.
  829.  
  830.      This allows any protocol that gathers data in packets or blocks to hand
  831.   a block of data to the decoder shell and go on about its business; the
  832.   shell will dole out the bytes to the decoder.  The downside (at least for
  833.   single-thread operating systems like DOS) is that actual decode/display
  834.   only takes place between packets, which gives the decode the appearence of
  835.   occuring in spurts.  It also makes basing a GIF decoder on true streaming
  836.   protocols like ZModem a bit trickier, as the decoder has to get some time
  837.   to do its job.
  838.  
  839.      The BPProtoGIF object provides two methods for the decoder.  The first,
  840.   the bpDLESeen virtual method, handles the "+" packet reception and
  841.   processing.  It is a function, returning True if it is successful and False
  842.   otherwise; the decoder should abort if the function returns False.  The
  843.   second is the bpGetGIFDataBlock function, which returns True and a packet's
  844.   worth of raw GIF stream data if successful, False if the packet reception
  845.   failed for some reason.  bpGetGIFDataBlock also returns a Boolean var
  846.   parameter showing whether the "TC" packet has been received, to make it
  847.   easier to see the end of the protocol session.
  848.  
  849.      When the main program sees the GIF decode startup ANSI sequence, it
  850.   should initialize itself and start looking for an <ENQ> from the port to
  851.   handshake the B+ protocol session.  Immediately after the <ENQ> should be
  852.   the <DLE> starting the host's "+" packet; the decoder calls bpDLESeen at
  853.   this point.  From here until we receive the "TC" terminating packet, all
  854.   port data will be B+ encapsulated GIF image data, to be processed by the
  855.   decoder.  We simply loop calling bpGetGIFDataPaket and handing the received
  856.   bytes to the decoder until done.  Review OLGIF for examples.
  857.  
  858.  
  859.   Video support considerations
  860.   ----------------------------
  861.  
  862.      There is a multitude of video hardware types available for PCs.  How do
  863.   we support 'em all?  Which should we support?
  864.  
  865.      In today's hardware market, SVGA cards are the most common video cards
  866.   sold.  SVGA support is a "must" in a GIF decoder.  But...  Any graphics
  867.   programmer will tell you: programming for SVGA can be a royal nightmare.
  868.   At least a dozen "common" main SVGA chipsets (more all the time) and, once
  869.   past the "IBM-standard" EGA/VGA modes, each having different mode
  870.   resolutions, different mode select numbers for those resolutions that are
  871.   the same, and different coding requirements to manage video memory
  872.   bankswitching and plotting.
  873.  
  874.      The TP BGI's provide a high level of device independence, and can be a
  875.   reasonable starting point for a GIF decoder.  But GIF's device-independent
  876.   nature doesn't keep device dependence from cropping up.  Because GIF
  877.   encoders and decoders are implemented on a wide variety of platforms, many
  878.   of which have video resolutions different from the common PC video modes, a
  879.   sizable percentage of GIF images are not "sized" to fit well on a PC screen
  880.   unless special handling is performed.  Also, since GIF is a high-resolution
  881.   format, it is commonly used with video hardware for which there is no BGI
  882.   support (including Targa, TIGA, IBM's new HGA and others).  Only a few
  883.   SVGA BGI drivers are available, and do not cover all common SVGA chipsets.
  884.   While decoder speed is not much of an issue in online environments until
  885.   the port bps rate reaches 9600 and above, a production offline decoder
  886.   that paints an image on the screen at BGI speeds will be considered
  887.   totally unacceptable. Finally, the BGI's are pretty topheavy considering
  888.   that GIF support only requires 2 video routines to do its job - a method
  889.   of setting the video card to the needed graphics mode and back to text
  890.   mode when done (a simple video BIOS call), and a routine to plot pixels or
  891.   raster lines on the screen.  An intelligently written set of routines done
  892.   in assembler that will detect and support all common video types from Herc
  893.   mono to SVGA, complete with SVGA chipset autodetect code and bankswitching
  894.   code, will take less code and data space than a single BGI driver linked
  895.   into the program.  Turbo Pascal 6.0's BASM makes an ideal environment for
  896.   the nessessary assembler, though I have stuck with straight TP in the demo
  897.   code for the sake of compatibility with earlier versions of TP and to be
  898.   more informative.  Although it can be done, it is no trivial job to write
  899.   straight TP code that directly manipulated SVGA hardware since most
  900.   chipsets require substantial diddling of ports; VGA and lower video types
  901.   can be dealt with in straight TP code quite acceptably, but assembler is
  902.   still preferred on these cards for best speed.
  903.  
  904.      The easy way out is to use the BIOS services for pixel plotting.  This
  905.   is only marginally faster than the BGI's, but easier to deal with and with
  906.   substantially less code overhead.  It is a dangerous way to go, though,
  907.   especially on CGA and earlier EGA and VGA cards - these older cards'
  908.   BIOS routines for plotting typically disable interrupts while plotting the
  909.   pixel, which in an online environment leads to dropped characters at the
  910.   port and a high percentage of resent data.  And on Hercules monochrome cards
  911.   it is unavailable.  I have mixed the best of both worlds in the demo
  912.   decoders (see GIFVIDEO.PAS), but a production program should use direct
  913.   hardware manipulation as far as possible for best speed and minimum
  914.   potential interference with the serial port.
  915.  
  916.      That said, there's a cure on the horizon: VESA.  VESA is a set of
  917.   standards for SVGA detection, mode selection and video manipulation that
  918.   provides a consistent set of mode resolutions, commands and data access to
  919.   eliminate most all the confusion between SVGA chipsets.  VESA is still new
  920.   but gaining support by leaps and bounds; all the major video manufacturers
  921.   support the VESA standards at least via a TSR.  Some are now bringing to
  922.   market cards that support VESA standards "hardwired" on the card,
  923.   although this is currently quite difficult due to the severely limited
  924.   room in most SVGA video BIOS ROM chips.  There are no VESA-compliant SVGA
  925.   BGIs available that I know of, but at least one is currently under
  926.   development and looks very good.  In this most recent version I have added
  927.   the nessessary VESA support to work with this code; it is in no way a
  928.   complete VESA interface, but it does work on all cards/drivers I have
  929.   been able to test with.
  930.  
  931.      On the subject of CGA and Hercules mono support:  I have included
  932.   support for these hardware types, but really only for their instructive
  933.   capability.  CGA and Herc mono simply do not have the size and/or color
  934.   resolution to do justice to the vast majority of GIF images today unless
  935.   all sorts of sneaky tricks are used.  With CGA and Herc mono rapidly
  936.   becomming a thing of the past (a low-end VGA card and mono analog monitor
  937.   costs about the same as a Herc card and mono TTL monitor and a *lot*
  938.   less than CGA), there's even less reason to expend effort and code space
  939.   on their support.  However, if you need such support, you will need to
  940.   implement some sort of dithering method to do color reduction.  In GIF
  941.   context, "dithering" an image means to perform colors reduction so that
  942.   the colors in the original image are mapped to best fit the available
  943.   palette on the local system.  There are a number of common color-reduction
  944.   dithers in use.  Most all work on the principle of error distribution;
  945.   spreading out the color error over surrounding pixels.  Just about all of
  946.   them require the decoder to have access to pixel data "in front of" the
  947.   current pixel - data that is unavailable to a decoder getting its data
  948.   from the serial port unless relatively complex buffer management is used.
  949.   Implementing such dithers is left to your skills and imagination, with the
  950.   following tip: there is a large base of dither technology available in
  951.   LIBrary 14 of the PICS forum on CIS, although practically none of it is in
  952.   Turbo Pascal.  If you can wade thru C and assembler code, you'll find lots
  953.   of good information with which to get started.  A good dither method to
  954.   reduce 256-color maps to 16 colors is important for EGA support as well.
  955.  
  956.      The switch from text mode to graphics mode is a sticky spot for online
  957.   GIF.  The header blocks must first be received so the decoder can
  958.   determine which mode to use before making the switch, so data will be
  959.   typically be streaming into the port when it is time to make the switch.
  960.   Most every video BIOS in captivity disables interrupts while it switches
  961.   modes, so at least a few bytes will be dropped by the port - causing a
  962.   defective packet and a resend.  This doesn't cause the protocol any grief
  963.   it can't handle, but it does slow things down unnessessarily.  The cure is
  964.   relatively simple: send the host an XOFF and wait for the port to become
  965.   "quiet" for some arbitrary length of time before making the mode switch.
  966.   Async Professional does not provide a method for waiting for a port to
  967.   quiese, so the demo adds a method for doing it; the method employs a sneaky
  968.   trick and goes against good OOP programming, so you may want to implement
  969.   such a method within the port handler object.  Don't forget to send an XON
  970.   after the mode switch is complete!
  971.  
  972.  
  973. ---- Beyond what's here: where to get help ----------------------------------
  974.  
  975.      The demo decoders are fully compliant with the 87a version of the GIF
  976.   spec.  They will also decode GIF streams built to the 89a version of the
  977.   spec, but will ignore all 89a extensions.  The DEGIF.OBJ module is
  978.   copyright (c)1989 Cyborg Software Systems, Inc., 3119 Cossell Drive,
  979.   Indianapolis, IN 46224  USA., and used by permission of its author.
  980.  
  981.      As mentioned before, dealing with the vagaries of SVGA hardware can be
  982.   a daunting task.  John Bridges, author of GRASP and PCPaint, is a past
  983.   master at it.  John periodically uploads a file to LIBrary 14 of the PICS
  984.   forum called VGAKIT.ZIP, that contains SVGA chipset autodetect and
  985.   bankswitch code, example plotting code, code to set and use special "not
  986.   supported by BIOS" modes on the VGA, and other juicy tidbits.  Be prepared
  987.   for MASM code written primarily to interface to MSC, but the conversion to
  988.   TASM and TP is fairly straightforward; John and I spent some time last
  989.   year working the kinks out so his MASM code requires minimal changes to
  990.   port to TP/TASM.
  991.  
  992.      The best allaround source for GIF help is the Developer's Den section
  993.   (17) of the PICS forum.  The place is haunted by some of the best and
  994.   brightest graphics minds in the world, all ready and willing to share their
  995.   expertise.  You'll find specialists in ray-tracing, format conversion,
  996.   fractals, high-end video, scanning, etc.
  997.  
  998.      I can be contacted via CIS at User ID# 70007,3574.  I frequent several
  999.   forums at least once a day, especially IBMCOM, PCVENB (TurboPower's section
  1000.   6), BPROGA and PICS.  The TurboPower folks will be happy to help you as
  1001.   well, but to help keep their support headaches in check I hope you'll
  1002.   contact me first; they may need to forward questions to me anyway.
  1003.   US Mail will reach me at:
  1004.  
  1005.      Ozarks West Software
  1006.      14150 Gleneagle Dr.
  1007.      Colorado Springs, CO  80921
  1008.  
  1009.  
  1010. {==== Reference Section ======================================================}
  1011.  
  1012.   The interface section of the OOBPLUS unit is provided below.
  1013.  
  1014. {-----------------------------------------------------------------------------}
  1015.  
  1016. {The following define is used to specify status updates at more frequent
  1017.  intervals than normal.  This makes the status display more informative and
  1018.  causes the "Time to go" field to just about tick like a clock on downloads,
  1019.  but it can have a negative effect on thruput at higher bps rates and can
  1020.  cause the CPS field to "jitter" somewhat, especially on uploads.}
  1021.  
  1022. {$DEFINE ShowRates}
  1023.  
  1024.  
  1025. {The following define enables support of online GIF decoding.  If you are not
  1026.  going to use GIF support, un-defining this can both save about 400 bytes of
  1027.  code space and allow you to use the unit even if you don't have TurboPower's
  1028.  Object Professional or Turbo Professional libraries.  The provided example
  1029.  program TERMBP.PAS does require Object Professional to compile.}
  1030.  
  1031. {$DEFINE SupportGIF}
  1032.  
  1033.  
  1034. {$IFNDEF UseOpro}
  1035. {$IFDEF SupportGIF}
  1036.     !!! The options selected are incompatible with this unit !!!
  1037. {$ENDIF}
  1038. {$ENDIF}
  1039.  
  1040. interface
  1041.  
  1042. uses
  1043.   DOS,
  1044. {$IFDEF UseOpro}
  1045.   OpCrt,
  1046. {$ELSE}
  1047. {$IFDEF UseTpro}
  1048.   TpCrt,
  1049. {$ELSE}
  1050.   Crt,
  1051. {$ENDIF}
  1052. {$ENDIF}
  1053.   ApMisc,
  1054.   ApTimer,
  1055.   ApPort,
  1056.   ApUart,
  1057.   OOCom,
  1058.   OOAbsPcl;
  1059.  
  1060. const
  1061.   UnitVers = '1.2f';
  1062.   UnitDate = '24-Apr-91';
  1063.  
  1064.     {consts needed here for status, continued from ApMisc}
  1065.   ecResync    = 9980;
  1066.   ecWaitACK   = 9981;
  1067.   ecDropout   = 9982;
  1068.   ecHostCan   = 9983;
  1069.   ecFileIO    = 9984;
  1070.   ecTryResume = 9985;
  1071.   ecHostResume= 9986;
  1072.   ecResumeOK  = 9987;
  1073.   ecResumeBad = 9988;
  1074.   ecOverwrite = 9989;
  1075.   ecUnPacket  = 9990;
  1076.  
  1077.   BP_Timeout_Max = 30;   {max allowed timeout per-char}
  1078.   BP_Error_Max = 10;     {max sequential errors}
  1079.   BP_Buffer_Max = 1032;  {largest data block available}
  1080.   BP_Abort_Max = 3;      {number of abort requests req'd to trigger Override}
  1081.   BP_SendAhead_Max = 2;  {max number of packets we can send ahead}
  1082.  
  1083.     {minimum <ESC><'I'> (and GIF support interrogation) response strings}
  1084. {$IFDEF SupportGIF}
  1085.  
  1086.   ESCI_Response : String[80] = '#IB1,SSxx,GF,PB,DT';
  1087.  
  1088.     {see the GIF87a or 89a spec for explanation of these codes}
  1089.   GIFReplyEGA = '#87a;1;0,320,200,4,0;0,640,200,2,2;0,640,350,4,2';
  1090.   GIFReplyCGA = '#87a;1;0,320,200,2,0;0,640,200,1,0';
  1091.   GIFReplyHGC = '#87a;1;0,720,350,1,0';
  1092.   GIFReply : String[60] = GIFReplyEGA;
  1093.  
  1094. {$ELSE}
  1095.  
  1096.   ESCI_Response : String[80] = '#IB1,SSxx,PB,DT';
  1097.  
  1098. {$ENDIF}
  1099.  
  1100.  
  1101. type
  1102.     {used by GetResumeProc for resume request handling}
  1103.   ResumeResultType = (xfrResume, xfrOverwrite, xfrRename, xfrAbort);
  1104.  
  1105.   BufferType = Array[0..BP_Buffer_Max] of Byte;  {a buffer of data}
  1106.   SABuffType =                                   {windowing buffer:}
  1107.     record
  1108.       Seq : Integer;                             {this sequence number}
  1109.       Num : Integer;                             {this packet's data size}
  1110.       Buf : BufferType;                          {this packet's data}
  1111.     end;
  1112.   SPackets = Array[0..BP_SendAhead_Max] of SABuffType;
  1113.  
  1114.   QuoteArray = Array[0..7] of Byte;         {for quoting params sets}
  1115.  
  1116. const
  1117.   DQFull    :      {all chars in ranges $00..$1F and $80..$9F}
  1118.     QuoteArray = ($FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF);
  1119.   DQDefault :      {ETX ENQ DLE XON XOFF NAK}
  1120.     QuoteArray = ($14, $00, $D4, $00, $00, $00, $00, $00);
  1121.   DQExtend  :      {same as DQDefault plus XON & XOFF w/ high bit set}
  1122.     QuoteArray = ($14, $00, $D4, $00, $00, $00, $50, $00);
  1123.   DQClassic :      {Classic B set, all chars in range $00..$1F}
  1124.     QuoteArray = ($FF, $FF, $FF, $FF, $00, $00, $00, $00);
  1125.  
  1126. type
  1127.   ParamsRecord =                            {xfer params record:}
  1128.     record
  1129.       WinSend,                              {send window size}
  1130.       WinRecv,                              {recv window size}
  1131.       BlkSize,                              {block size (* 128)}
  1132.       ChkType  : Byte;                      {check type, chksum or CRC}
  1133.       QuoteSet : QuoteArray;                {chars to quote}
  1134.       DROpt,                                {DL Recovery option}
  1135.       UROpt,                                {UL Recovery option}
  1136.       FIOpt    : Byte;                      {File Info option}
  1137.     end;
  1138.  
  1139.     {protocol direction options}
  1140.   DirectionType = (Upload, Download);
  1141.  
  1142.   BPProtocolPtr = ^BPProtocol;
  1143.   GetResumeProc = function(BPP : BPProtocolPtr) : ResumeResultType;
  1144.   ChkAbortProc = function : Boolean;
  1145.  
  1146.   BPProtocol =                               {abstract BPlus object:}
  1147.     object(AbstractProtocol)
  1148.       Ch        : Integer;                   {curr char sent/recd}
  1149.       Quoted    : Boolean;                   {true if last ch recd was quoted}
  1150.       QuoteTable: Array[0..255] of Byte;     {our active quoting table}
  1151.       Checksum  : Word;                      {may hold CRC}
  1152.       Direction : DirectionType;             {upload or download}
  1153.       DefResume : ResumeResultType;          {default resume handling}
  1154.       GetResume : GetResumeProc;             {determine how to handle resume}
  1155.       ChkAbort  : ChkAbortProc;              {see if user wants an abort}
  1156.  
  1157.       HisParams : ParamsRecord;              {host's parameters}
  1158.       OurParams : ParamsRecord;              {our parameters}
  1159.  
  1160.       AbortCount: Integer;                   {# of abort requests so far}
  1161.       ResumeFlag: Boolean;                   {true if resuming an aborted dl}
  1162.       ResumeOK  : Boolean;                   {true if resume was successful}
  1163.       Aborting  : Boolean;                   {true if processing abort}
  1164.       FatalAbort: Boolean;                   {true if OverrideAbort}
  1165.       ShowStatus: Boolean;                   {False only for GIF}
  1166.       PacketRecd: Boolean;                   {true if packet recd in SendPacket}
  1167.       BPlus     : Boolean;                   {true if in full B+ mode}
  1168.       ClassicB  : Boolean;                   {true for "original" B proto}
  1169.       UseSQuote : Boolean;                   {true if using special quote set}
  1170.       SQuoteSet : QuoteArray;                {user's specified quote set}
  1171.  
  1172.       RSize     : Integer;                   {size of last recd buffer}
  1173.       BuffeRSize: Integer;                   {current allowed recv size}
  1174.       RBuffer   : BufferType;                {receive buffer}
  1175.       SBuffer   : SPackets;                  {sending buffers}
  1176.       SeqNum    : Integer;                   {current sequence number}
  1177.       Next2ACK  : Integer;                   {packet pending ACK}
  1178.       Next2Fill : Integer;                   {packet to load for send}
  1179.       SAMax     : Integer;                   {highest current sendahead cnt}
  1180.       SAWaiting : Integer;                   {# of packets outstanding ACKs}
  1181.       SAErrors  : Integer;                   {keep track of SendAhead errors}
  1182.  
  1183.       R_Raw     : LongInt;                   {vars for status display}
  1184.       R_Packets : LongInt;
  1185.       S_Raw     : LongInt;
  1186.       S_Packets : LongInt;
  1187. {$IFDEF ShowRates}
  1188.       R_Counter : LongInt;
  1189.       S_Counter : LongInt;
  1190. {$ENDIF}
  1191.  
  1192.       constructor Init(AP : AbstractPortPtr);
  1193.       destructor Done; virtual;
  1194.  
  1195.       {...public methods called by terminal handlers}
  1196.       procedure bpHandleENQ;
  1197.         {-handle an <ENQ> from host}
  1198.       procedure bpHandleESCI;
  1199.         {-handle <ESC><'I'> (VT52 terminal capabilities inquiry) from host}
  1200.       function bpDLESeen : Boolean; virtual;
  1201.         {-called when <DLE> seen from host, starts protocol}
  1202.  
  1203.       {...other publics}
  1204.       procedure bpSetResumeProc(RP : GetResumeProc);
  1205.         {-set our ResumeProc for this instance}
  1206.       procedure bpSetChkAbortProc(CAP : ChkAbortProc);
  1207.         {-set our ChkAbortProc for this instance}
  1208.       procedure bpSendACK;
  1209.         {-acknowledge receipt of a complete packet}
  1210.  
  1211.       {...private methods}
  1212.       procedure UpdateStatus(W : Word);
  1213.       procedure UpdateQuoteTable(QS : QuoteArray);
  1214.       procedure QuoteThis(Value : Integer);
  1215.       procedure apResetProtocol; virtual;
  1216.       procedure apUpdateBlockCheck(CurByte : Byte); virtual;
  1217.       function CheckAbort : Boolean;
  1218.       procedure SendByte(C : Char);
  1219.       procedure SendQuotedByte(I : Integer);
  1220.       procedure SendNAK;
  1221.       procedure SendENQ;
  1222.       function IncSequence(Value : Integer) : Integer;
  1223.       function ReadByte : Boolean;
  1224.       function ReadQuotedByte : Boolean;
  1225.       procedure SendFailure(Reason : String);
  1226.       function ReadPacket(LeadInSeen, FromSend : Boolean) : Boolean;
  1227.       procedure SendData(BNum : Integer);
  1228.       function IncSA(Value : Integer) : Integer;
  1229.       function ReSync : Integer;
  1230.       function GetACK : Boolean;
  1231.       function SAFlush : Boolean;
  1232.       function SendPacket(Size : Integer) : Boolean;
  1233.       function SendTransport : Boolean;
  1234.       procedure ProcessTransportParams(SendXPortInfo : Boolean);
  1235.       procedure bpInitVars;
  1236.     end;
  1237.  
  1238.   BPProtoFTPPtr = ^BPProtoFTP;
  1239.   BPProtoFTP =
  1240.     object(BPProtocol)
  1241.       constructor Init(AP : AbstractPortPtr;
  1242.                        DefaultResume : ResumeResultType);
  1243.       destructor Done; virtual;
  1244.  
  1245.       {...public methods}
  1246.       function bpDLESeen : Boolean; virtual;
  1247.  
  1248.       {...virtual methods}
  1249.       procedure apPrepareReading; virtual;
  1250.       procedure apFinishReading; virtual;
  1251.       procedure apFinishWriting; virtual;
  1252.       procedure apPrepareWriting; virtual;
  1253.  
  1254.       {...private methods}
  1255.       procedure SendFile;
  1256.       procedure RecvFile;
  1257.     end;
  1258.  
  1259. {$IFDEF SupportGIF}
  1260.   BPProtoGIFPtr = ^BPProtoGIF;
  1261.   BPProtoGIF =
  1262.     object(BPProtocol)
  1263.       constructor Init(AP : AbstractPortPtr);
  1264.       destructor Done; virtual;
  1265.  
  1266.       {...Public methods}
  1267.       function bpDLESeen : Boolean; virtual;
  1268.       function bpGetGIFDataBlock(var P;
  1269.                                  var PSize : Word;
  1270.                                  var IsLast : Boolean) : Boolean;
  1271.     end;
  1272. {$ENDIF}
  1273.  
  1274. function bpStatusStr(Code : Word) : String;
  1275. procedure NoUserStatus(AP : AbstractProtocolPtr; First, Last : Boolean);
  1276.  
  1277.  
  1278.  
  1279. {===== Procedure/Function/Method Reference ===================================}
  1280.  
  1281. This section provides details on the public and virtual methods of the
  1282. various BPlus protocol objects.
  1283.  
  1284. {----- BPProtocol object -----------------------------------------------------}
  1285.  
  1286. constructor Init(AP : AbstractPortPtr);
  1287. Purpose:
  1288.   Initialize BPlus protocol instance, including all shared vars from
  1289.   AbstractProtocol and those BPProtocol vars that are instance-dependent.
  1290.   Like other protocol objects derived from AbstractProtocol, if the constructor
  1291.   fails the reason code is returned in the AsyncStatus global.
  1292.  
  1293. Example:
  1294.   {...}
  1295.   Var
  1296.     OurBPlus : BPProtocol;
  1297.   {...}
  1298.   if NOT OurBPlus.Init(OurPortPtr) then
  1299.     WriteLn('Error ',AsyncStatus,' initializing BPlus protocol object!');
  1300.   {...}
  1301.  
  1302.  
  1303.  
  1304.  
  1305. destructor Done; virtual;
  1306. Purpose:
  1307.   Dispose of BPProtocol instance when processing is complete.
  1308.  
  1309.  
  1310.  
  1311.  
  1312. procedure bpHandleENQ;
  1313. Purpose:
  1314.   Perform protocol-dependent processing when a <ENQ> char (ASCII $05) is
  1315.   received at the serial port.  This method initializes some internal vars
  1316.   and sends the proper response back to the CIS host.
  1317.  
  1318. Example:
  1319.   {...}
  1320.     case RecdChar of
  1321.       #5:
  1322.         OurBPlus.bpHandleENQ;
  1323.       else
  1324.         Write(RecdChar);
  1325.   {...}
  1326.  
  1327. See also:
  1328.   bpHandleESCI, bpDLESeen
  1329.  
  1330.  
  1331.  
  1332.  
  1333. procedure bpHandleESCI;
  1334. Purpose:
  1335.   Handle responding to <ESC><'I'> inquiry from CIS host.  See the detailed
  1336.   description in the protocol spec document for more information on the
  1337.   codes that are used to build the response string.
  1338.  
  1339. Example:
  1340.   {...}
  1341.   if (LastRecdChar = #27) and (RecdChar = 'I') then
  1342.     OurBPlus.bpHandleESCI;
  1343.   {...}
  1344.  
  1345. See also:
  1346.   bpHandleENQ, bpDLESeen
  1347.  
  1348.  
  1349.  
  1350.  
  1351. function bpDLESeen : Boolean; virtual;
  1352. Purpose:
  1353.   Called when a <DLE> char (ASCII $10) is received from the CIS host.  This
  1354.   function calls the main protocol processing loop.  It returns True if
  1355.   protocol processing completed successfully, or False if a error occurs
  1356.   during protocol handshaking or if the protocol session is aborted for any
  1357.   reason.  Note that in the BBProtocol object this is only an abstract method.
  1358.  
  1359. Example:
  1360.   {...}
  1361.   if (RecdChar = cDLE) then
  1362.     if OurBPlus.bpDLESeen then ;
  1363.   {...}
  1364.   WRONG!  In the BPProtocol base object, bpDLESeen is an ABSTRACT method that
  1365.   will generate a runtime error (211) if called directly.
  1366.  
  1367. See also:
  1368.   bpHandleENQ, bpHandleESCI
  1369.  
  1370.  
  1371.  
  1372.  
  1373.  
  1374. procedure bpSetResumeProc(RP : GetResumeProc);
  1375. Purpose:
  1376.   Assign a function to the BPProtocol object's GetResume proc pointer to tell
  1377.   the protocol which type of handling should be used for resuming an aborted
  1378.   download.  When a download is started and the protocol determines that a
  1379.   file of the same name as the file being downloaded already exists, it can
  1380.   proceed in one of several ways: it can abort in order not to risk
  1381.   overwriting the existing file, it can overwrite the existing file
  1382.   regardless, it can rename the new file being downloaded so as not to
  1383.   conflict, or it can attempt a resume of a previous download.  No one choice
  1384.   is appropriate for all occasions, so this hook is provided for an outside
  1385.   function to tell the protocol how to proceed.  The function must be
  1386.   compiled using the FAR model and cannot be nested within another procedure
  1387.   or function.  It takes the following form:
  1388.  
  1389.     function GetResumeFunc(BPP : BPProtocolPtr) : ResumeResultType;
  1390.  
  1391.   Typically this function prompts the user what to do and returns his/her
  1392.   choice.  See the definition of the ResumeResultType above.
  1393.  
  1394. Example:
  1395.   {...}
  1396.   OurBPlus.Init(OurPortPtr);
  1397.   OurBPlus.bpSetResumeProc(GetResumeFunc);
  1398.   {...}
  1399.  
  1400. See also:
  1401.   bpSetChkAbortProc, and the type declaration of ResumeResultType above.
  1402.  
  1403.  
  1404.  
  1405.  
  1406.  
  1407. procedure bpSetChkAbortProc(CAP : ChkAbortProc);
  1408. Purpose:
  1409.   Assign a function to determine if the user wishes to abort the protocol
  1410.   session.  Typically this will be set to point to a function that returns
  1411.   True of the user has requested an abort (by pressing a key, clicking the
  1412.   mouse on a hotspot, etc.) or False otherwise.  Like bpSetResumeProc, the
  1413.   function passed to this procedure must be compiled under the FAR model and
  1414.   not be nested within any other procedure or function.  The function takes
  1415.   the form:
  1416.  
  1417.     function ChkAbortFunc : Boolean;
  1418.  
  1419. Example:
  1420.   {...}
  1421.   OurBPlus.Init(OurPortPtr);
  1422.   OurBPlus.bpSetChkAbortProc(ChkAbortFunc);
  1423.   {...}
  1424.  
  1425. See also:
  1426.   bpSetResumeProc
  1427.  
  1428.  
  1429.  
  1430. {----- BPProtoFTP object -----------------------------------------------------}
  1431.  
  1432. constructor Init(AP : AbstractPortPtr; DefaultResume : ResumeResultType);
  1433. Purpose:
  1434.   Initialize BPProtoFTP object.  The DefaultResume parameter provides the
  1435.   default handling type for resume attempts in case no GetResumeProc has
  1436.   been assigned, so totally automated systems such as "CIS navigators" can
  1437.   continue processing without user intervention.
  1438.  
  1439. Example:
  1440.   {...}
  1441.   var OurBPFTP : BPProtoFTP;
  1442.   {...}
  1443.   OurBPFTP.Init(OurPortPtr,xfrOverWrite);
  1444.   {...}
  1445.  
  1446. See also:
  1447.   AbstractProtocol.InitCustom, BPProtocol.Init
  1448.  
  1449.  
  1450.  
  1451.  
  1452. destructor Done; virtual;
  1453. Purpose:
  1454.   Dispose of BPProtoFTP instance when processing is complete.
  1455.  
  1456.  
  1457.  
  1458.  
  1459. procedure apPrepareReading; virtual;
  1460. Purpose:
  1461.   Prepare for transmitting data via the protocol (usually opens the file to
  1462.   be uploaded).
  1463.  
  1464. See also:
  1465.   The other AbstractProtocol child objects' apPrepareReading methods.
  1466.  
  1467.  
  1468.  
  1469.  
  1470. procedure apFinishReading; virtual;
  1471. Purpose:
  1472.   Perform any nessessary cleanup after the upload is finished (usually closes
  1473.   the file uploaded).
  1474.  
  1475. See also:
  1476.   The other AbstractProtocol child objects' apFinishReading methods.
  1477.  
  1478.  
  1479.  
  1480.  
  1481.  
  1482. procedure apPrepareWriting; virtual;
  1483. Purpose:
  1484.   Prepare for receiving data via the protocol (usually opens the file to
  1485.   be downloaded).  In this instance the method also checks if a resume
  1486.   attempt is needed.
  1487.  
  1488. See also:
  1489.   The other AbstractProtocol child objects' apPrepareWriting methods.
  1490.  
  1491.  
  1492.  
  1493.  
  1494.  
  1495. procedure apFinishWriting; virtual;
  1496. Purpose:
  1497.   Perform any nessessary cleanup after the download is finished (usually
  1498.   closes the received file).
  1499.  
  1500. See also:
  1501.   The other AbstractProtocol child objects' apFinishWriting methods.
  1502.  
  1503.  
  1504.  
  1505.  
  1506.  
  1507. function bpDLESeen : Boolean; virtual;
  1508. Purpose:
  1509.   Called when a <DLE> char (ASCII $10) is received from the CIS host.  This
  1510.   function calls the main protocol processing loop.  It returns True if
  1511.   protocol processing completed successfully, or False if a error occurs
  1512.   during protocol handshaking or if the protocol session is aborted for any
  1513.   reason.  In this BPProtoFTP instance, bpDLESeen either receives the "+"
  1514.   packet and initializes the nessessary internal variables, or receives the
  1515.   initial "TD" packet, verifies that all provided parameters are correct, and
  1516.   sends or receives the file named in the "TD" packet.
  1517.  
  1518. Example:
  1519.   {...}
  1520.   if (RecdChar = cDLE) then
  1521.     if OurBPFTP.bpDLESeen then ;
  1522.   {...}
  1523.  
  1524. See also:
  1525.   BPProtocol.bpDLESeen
  1526.  
  1527.  
  1528. {----- BPProtoGIF object -----------------------------------------------------}
  1529.  
  1530. constructor Init(AP : AbstractPortPtr);
  1531. Purpose:
  1532.   Initialize BPProtoGIF object.
  1533.  
  1534. Example:
  1535.   {...}
  1536.   var OurBPGIF : BPProtoGIF;
  1537.   {...}
  1538.   OurBPGIF.Init(OurPortPtr);
  1539.   {...}
  1540.  
  1541. See also:
  1542.   AbstractProtocol.InitCustom, BPProtocol.Init
  1543.  
  1544.  
  1545.  
  1546.  
  1547. destructor Done; virtual;
  1548. Purpose:
  1549.   Dispose of BPProtoGIF instance when processing is complete.
  1550.  
  1551.  
  1552.  
  1553.  
  1554. function bpDLESeen : Boolean; virtual;
  1555. Purpose:
  1556.   Called when a <DLE> char (ASCII $10) is received from the CIS host.  This
  1557.   function calls the main protocol processing loop.  It returns True if
  1558.   protocol processing completed successfully, or False if a error occurs
  1559.   during protocol handshaking or if the protocol session is aborted for any
  1560.   reason.  In this BPProtoGIF instance, bpDLESeen receives the "+" packet and
  1561.   initializes the nessessary internal variables; all other protocol
  1562.   processing is handled by the bpGetGIFDataBlock and bpSendACK methods.
  1563.  
  1564. Example:
  1565.   {...}
  1566.   if (RecdChar = cDLE) then
  1567.     if OurBPFTP.bpDLESeen then ;
  1568.   {...}
  1569.  
  1570. See also:
  1571.   BPProtocol.bpDLESeen, BPProtoFTP.bpDLESeen
  1572.  
  1573.  
  1574.  
  1575.  
  1576. function bpGetGIFDataBlock(var P;
  1577.                            var PSize : Word;
  1578.                            var IsLast : Boolean) : Boolean;
  1579. Purpose:
  1580.   Return a block data from the protocol handler for decoding.  P is a var
  1581.   parameter denoting a buffer at least large enough to hold one full packet's
  1582.   worth of data.  On exit, PSize holds the number of bytes placed in P, and
  1583.   the IsLast parameter is set True if the packet received was a "TC"
  1584.   termination packet or False otherwise.
  1585.  
  1586.   The function returns False if the protocol terminates (a Failure packet is
  1587.   received or too many consecutive protocol errors occur), otherwise it
  1588.   returns True.  Defective packets are automatically NAKed within the
  1589.   protocol, but _your_ code is responsible for sending the ACK for a good
  1590.   packet (see bpSendACK above).
  1591.  
  1592. Example:
  1593.   {...}
  1594.   var DecodeBuffer : Array[1..1024] of Byte;
  1595.       DecodeSize : Word;
  1596.       IsLastPacket : Boolean;
  1597.   {...}
  1598.   if NOT bpGetGIFDataBlock(DecodeBuffer,DecodeSize,IsLastPacket) then
  1599.     {handle error}
  1600.   else
  1601.     {decode/display image data now in DecodeBuffer}
  1602.  
  1603. See also:
  1604.   The example code in the OFLGIF.PAS file included in the package.
  1605.  
  1606.  
  1607. (* EOF *)
  1608.  
  1609.